{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8fa27cbc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7.12600549e-067, 1.20737151e-153, 1.20766849e-153, ...,\n",
       "       1.72423412e-047, 4.64999190e-086, 2.90739885e-033])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import json\n",
    "datafile='./housing.data'\n",
    "data=np.fromfile(datafile,sep='')\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3a13b29a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "iter 9, loss 5.143394325795511\n",
      "iter 19, loss 3.0979241942259876\n",
      "iter 29, loss 2.082241020617026\n",
      "iter 39, loss 1.5673801618157397\n",
      "iter 49, loss 1.296620473507743\n",
      "iter 59, loss 1.1453399043319763\n",
      "iter 69, loss 1.05301557174352\n",
      "iter 79, loss 0.9902292156463154\n",
      "iter 89, loss 0.9426576903842504\n",
      "iter 99, loss 0.9033048096880774\n",
      "iter 109, loss 0.868732003041364\n",
      "iter 119, loss 0.837229250968144\n",
      "iter 129, loss 0.807927474161227\n",
      "iter 139, loss 0.7803677341465795\n",
      "iter 149, loss 0.7542920908532763\n",
      "iter 159, loss 0.7295420168915829\n",
      "iter 169, loss 0.7060090054240882\n",
      "iter 179, loss 0.6836105084697766\n",
      "iter 189, loss 0.6622781710179412\n",
      "iter 199, loss 0.6419520361168637\n",
      "iter 209, loss 0.6225776517869489\n",
      "iter 219, loss 0.6041045903195836\n",
      "iter 229, loss 0.5864856570315077\n",
      "iter 239, loss 0.5696764374763879\n",
      "iter 249, loss 0.5536350125932015\n",
      "iter 259, loss 0.5383217588525027\n",
      "iter 269, loss 0.5236991929680567\n",
      "iter 279, loss 0.5097318413761649\n",
      "iter 289, loss 0.4963861247069634\n",
      "iter 299, loss 0.48363025234390233\n",
      "iter 309, loss 0.4714341245401978\n",
      "iter 319, loss 0.45976924072044867\n",
      "iter 329, loss 0.4486086131659099\n",
      "iter 339, loss 0.43792668556597936\n",
      "iter 349, loss 0.4276992560632111\n",
      "iter 359, loss 0.4179034044959738\n",
      "iter 369, loss 0.40851742358635523\n",
      "iter 379, loss 0.3995207538478764\n",
      "iter 389, loss 0.39089392200622347\n",
      "iter 399, loss 0.382618482740513\n",
      "iter 409, loss 0.3746769635645124\n",
      "iter 419, loss 0.36705281267772816\n",
      "iter 429, loss 0.35973034962581096\n",
      "iter 439, loss 0.35269471861856694\n",
      "iter 449, loss 0.3459318443621334\n",
      "iter 459, loss 0.33942839026966587\n",
      "iter 469, loss 0.3331717189222164\n",
      "iter 479, loss 0.32714985465842517\n",
      "iter 489, loss 0.3213514481781961\n",
      "iter 499, loss 0.31576574305173283\n",
      "iter 509, loss 0.3103825440311681\n",
      "iter 519, loss 0.30519218706757245\n",
      "iter 529, loss 0.3001855109413672\n",
      "iter 539, loss 0.29535383041913843\n",
      "iter 549, loss 0.29068891085453674\n",
      "iter 559, loss 0.2861829441553933\n",
      "iter 569, loss 0.28182852604338504\n",
      "iter 579, loss 0.27761863453655333\n",
      "iter 589, loss 0.27354660958874766\n",
      "iter 599, loss 0.2696061338236152\n",
      "iter 609, loss 0.265791214304132\n",
      "iter 619, loss 0.26209616528184804\n",
      "iter 629, loss 0.258515591873034\n",
      "iter 639, loss 0.25504437461176843\n",
      "iter 649, loss 0.2516776548326958\n",
      "iter 659, loss 0.24841082083874044\n",
      "iter 669, loss 0.24523949481147195\n",
      "iter 679, loss 0.24215952042409844\n",
      "iter 689, loss 0.2391669511192288\n",
      "iter 699, loss 0.23625803901558054\n",
      "iter 709, loss 0.2334292244097483\n",
      "iter 719, loss 0.23067712584097294\n",
      "iter 729, loss 0.22799853068858245\n",
      "iter 739, loss 0.22539038627340988\n",
      "iter 749, loss 0.22284979143604464\n",
      "iter 759, loss 0.22037398856623475\n",
      "iter 769, loss 0.21796035605914357\n",
      "iter 779, loss 0.2156064011754777\n",
      "iter 789, loss 0.21330975328373866\n",
      "iter 799, loss 0.2110681574640261\n",
      "iter 809, loss 0.20887946845393043\n",
      "iter 819, loss 0.2067416449181002\n",
      "iter 829, loss 0.20465274402406475\n",
      "iter 839, loss 0.20261091630783168\n",
      "iter 849, loss 0.20061440081366638\n",
      "iter 859, loss 0.1986615204933024\n",
      "iter 869, loss 0.19675067785062839\n",
      "iter 879, loss 0.19488035081864621\n",
      "iter 889, loss 0.19304908885621125\n",
      "iter 899, loss 0.1912555092527351\n",
      "iter 909, loss 0.1894982936296714\n",
      "iter 919, loss 0.18777618462820625\n",
      "iter 929, loss 0.18608798277314595\n",
      "iter 939, loss 0.18443254350353408\n",
      "iter 949, loss 0.18280877436103968\n",
      "iter 959, loss 0.18121563232764162\n",
      "iter 969, loss 0.17965212130459232\n",
      "iter 979, loss 0.1781172897250724\n",
      "iter 989, loss 0.1766102282933619\n",
      "iter 999, loss 0.17513006784373505\n"
     ]
    },
    {
     "data": {
      "image/png": "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atXX1+vWW2/V1q1bB5UxxuiHP/yhGhoaVF5eruuvv14fffTRoDKxWEz33HOP6urqVFlZqa985Svau3evnT/KmNLS0iKPx6OlS5fmr9HO1tm3b59uv/121dbWqqKiQpdccolaW1vzr9PWo5dMJvXwww+rqalJ5eXlmjFjhh555BGl0+l8Gdq5cH/4wx/05S9/WQ0NDfJ4PPqv//qvQa9b1aYdHR264447FA6HFQ6Hdccdd+jYsWOj/wGMC6xcudIEAgHz9NNPmy1btpglS5aYyspKs3v3bqerNiZ86UtfMs8884z58MMPzaZNm8z8+fPN2Wefbbq6uvJlHn/8cVNdXW1efPFFs3nzZvO1r33NTJ482USj0XyZu+++20yZMsWsXr3abNiwwdxwww3m4osvNslk0okf64z27rvvmunTp5uLLrrILFmyJH+ddrbG0aNHzbRp08w3vvEN884775idO3ea1157zWzfvj1fhrYevR/96EemtrbW/OpXvzI7d+40//mf/2mqqqrM8uXL82Vo58K9+uqr5qGHHjIvvviikWRefvnlQa9b1aY333yzaW5uNmvXrjVr1641zc3NZsGCBaOuvyuCxRVXXGHuvvvuQddmzpxpHnjgAYdqNLa1t7cbSWbNmjXGGGPS6bSZNGmSefzxx/Nl+vr6TDgcNj/96U+NMcYcO3bMBAIBs3LlynyZffv2Ga/Xa37zm9/Y+wOc4To7O815551nVq9eba677rp8sKCdrbNs2TIzd+7cYV+nra0xf/58861vfWvQtb/6q78yt99+uzGGdrbC8cHCqjbdsmWLkWTefvvtfJl169YZSeZPf/rTqOo85odC4vG4WltbNW/evEHX582bp7Vr1zpUq7EtEolIkiZMmCBJ2rlzpw4ePDiojUOhkK677rp8G7e2tiqRSAwq09DQoObmZn4Px1m0aJHmz5+vm266adB12tk6r7zyiubMmaOvfvWrqq+v16WXXqqnn346/zptbY25c+fq9ddf17Zt2yRJ77//vt566y3dcsstkmjnYrCqTdetW6dwOKwrr7wyX+bzn/+8wuHwqNvd9kPIrHb48GGlUilNnDhx0PWJEyfq4MGDDtVq7DLG6P7779fcuXPV3NwsSfl2HKqNd+/enS8TDAY1fvz4E8rwe+i3cuVKbdiwQevXrz/hNdrZOjt27NCKFSt0//336/vf/77effdd3XvvvQqFQrrzzjtpa4ssW7ZMkUhEM2fOlM/nUyqV0qOPPqrbbrtNEv+mi8GqNj148KDq6+tP+Pz6+vpRt/uYDxY5xx/Bboyx9Fj2UrF48WJ98MEHeuutt054bSRtzO+hX1tbm5YsWaLf/e53KisrG7Yc7Tx66XRac+bM0WOPPSZJuvTSS/XRRx9pxYoVuvPOO/PlaOvRWbVqlZ577jk9//zzuuCCC7Rp0yYtXbpUDQ0Nuuuuu/LlaGfrWdGmQ5W3ot3H/FBIXV2dfD7fCQmrvb39hESHk7vnnnv0yiuv6I033hh0tP2kSZMk6aRtPGnSJMXjcXV0dAxbptS1traqvb1ds2fPlt/vl9/v15o1a/STn/xEfr8/30608+hNnjxZ559//qBrs2bN0p49eyTxb9oq3/3ud/XAAw/o61//ui688ELdcccduu+++9TS0iKJdi4Gq9p00qRJ+uyzz074/EOHDo263cd8sAgGg5o9e7ZWr1496Prq1at19dVXO1SrscUYo8WLF+ull17S73//ezU1NQ16vampSZMmTRrUxvF4XGvWrMm38ezZsxUIBAaVOXDggD788EN+D1k33nijNm/erE2bNuVvc+bM0cKFC7Vp0ybNmDGDdrbINddcc8KS6W3btmnatGmS+DdtlZ6eHnm9g/+M+Hy+/HJT2tl6VrXpVVddpUgkonfffTdf5p133lEkEhl9u49q6ucZIrfc9Gc/+5nZsmWLWbp0qamsrDS7du1yumpjwre//W0TDofNm2++aQ4cOJC/9fT05Ms8/vjjJhwOm5deesls3rzZ3HbbbUMub5o6dap57bXXzIYNG8wXv/jFkl4ydjoGrgoxhna2yrvvvmv8fr959NFHzSeffGJ+/vOfm4qKCvPcc8/ly9DWo3fXXXeZKVOm5JebvvTSS6aurs5873vfy5ehnQvX2dlpNm7caDZu3GgkmSeeeMJs3Lgxv4WCVW168803m4suusisW7fOrFu3zlx44YUsNx3oX//1X820adNMMBg0l112WX6pJE5N0pC3Z555Jl8mnU6bH/zgB2bSpEkmFAqZa6+91mzevHnQ5/T29prFixebCRMmmPLycrNgwQKzZ88em3+aseX4YEE7W+eXv/ylaW5uNqFQyMycOdM89dRTg16nrUcvGo2aJUuWmLPPPtuUlZWZGTNmmIceesjEYrF8Gdq5cG+88caQ/02+6667jDHWtemRI0fMwoULTXV1tamurjYLFy40HR0do64/x6YDAADLjPk5FgAA4MxBsAAAAJYhWAAAAMsQLAAAgGUIFgAAwDIECwAAYBmCBQAAsAzBAgAAWIZgAQAALEOwAAAAliFYAAAAyxAsAACAZf4/uHStUeE9CWQAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import json\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "class Network(object):\n",
    "    \n",
    "    def __init__(self, num_of_weights):\n",
    "        # 随机产生w的初始值\n",
    "        # 为了保持程序每次运行结果的一致性，\n",
    "        # 此处设置固定的随机数种子\n",
    "        np.random.seed(0)\n",
    "        self.w = np.random.randn(num_of_weights, 1)\n",
    "        self.b = 0.\n",
    "        \n",
    "    def forward(self, x):\n",
    "        z = np.dot(x, self.w) + self.b\n",
    "        return z\n",
    "    \n",
    "    def loss(self, z, y):\n",
    "            error = z - y\n",
    "            cost = error * error\n",
    "            cost = np.mean(cost)\n",
    "            return cost\n",
    "        \n",
    "    def gradient(self, x, y):\n",
    "        z = self.forward(x)\n",
    "        gradient_w = (z-y)*x\n",
    "        gradient_w = np.mean(gradient_w, axis=0)\n",
    "        gradient_w = gradient_w[:, np.newaxis]\n",
    "        gradient_b = (z - y)\n",
    "        gradient_b = np.mean(gradient_b)\n",
    "        \n",
    "        return gradient_w, gradient_b\n",
    "    \n",
    "    def update(self, gradient_w, gradient_b, eta = 0.01):\n",
    "        self.w = self.w - eta * gradient_w\n",
    "        self.b = self.b - eta * gradient_b\n",
    "        \n",
    "    def train(self, x, y, iterations=100, eta=0.01):\n",
    "        losses = []\n",
    "        for i in range(iterations):\n",
    "            z = self.forward(x)\n",
    "            L = self.loss(z, y)\n",
    "            gradient_w, gradient_b = self.gradient(x, y)\n",
    "            self.update(gradient_w, gradient_b, eta)\n",
    "            losses.append(L)\n",
    "            if (i+1) % 10 == 0:\n",
    "                print('iter {}, loss {}'.format(i, L))\n",
    "        return losses\n",
    "\n",
    "def load_data():\n",
    "    # 从文件导入数据\n",
    "    datafile = './housing.data'\n",
    "    data = np.fromfile(datafile, sep=' ')\n",
    "\n",
    "    # 每条数据包括14项，其中前面13项是影响因素，第14项是相应的房屋价格中位数\n",
    "    feature_names = [ 'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', \\\n",
    "                      'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV' ]\n",
    "    feature_num = len(feature_names)\n",
    "\n",
    "    # 将原始数据进行Reshape，变成[N, 14]这样的形状\n",
    "    data = data.reshape([data.shape[0] // feature_num, feature_num])\n",
    "\n",
    "    # 将原数据集拆分成训练集和测试集\n",
    "    # 这里使用80%的数据做训练，20%的数据做测试\n",
    "    # 测试集和训练集必须是没有交集的\n",
    "    ratio = 0.8\n",
    "    offset = int(data.shape[0] * ratio)\n",
    "    training_data = data[:offset]\n",
    "\n",
    "    # 计算训练集的最大值，最小值\n",
    "    maximums, minimums = training_data.max(axis=0), training_data.min(axis=0)\n",
    "\n",
    "    # 对数据进行归一化处理\n",
    "    for i in range(feature_num):\n",
    "        data[:, i] = (data[:, i] - minimums[i]) / (maximums[i] - minimums[i])\n",
    "\n",
    "    # 训练集和测试集的划分比例\n",
    "    training_data = data[:offset]\n",
    "    test_data = data[offset:]\n",
    "    return training_data, test_data\n",
    "\n",
    "#获取数据\n",
    "train_data, test_data = load_data()\n",
    "x = train_data[:, :-1]\n",
    "y = train_data[:, -1:]\n",
    "# 创建网络\n",
    "net = Network(13)\n",
    "num_iterations=1000\n",
    "# 启动训练\n",
    "losses = net.train(x,y, iterations=num_iterations, eta=0.01)\n",
    "\n",
    "# 画出损失函数的变化趋势\n",
    "plot_x = np.arange(num_iterations)\n",
    "plot_y = np.array(losses)\n",
    "plt.plot(plot_x, plot_y)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "954c645b",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请选择\n",
      "1 直接训练\n",
      "2 使用已有的模型\n",
      "1\n",
      "Epoch   0 , loss = 2.6179\n",
      "Epoch   0 , loss = 1.1911\n",
      "Epoch   0 , loss = 1.0459\n",
      "Epoch   0 , loss = 0.9001\n",
      "Epoch   0 , loss = 0.7533\n",
      "Epoch   1 , loss = 0.7612\n",
      "Epoch   1 , loss = 0.5734\n",
      "Epoch   1 , loss = 0.5418\n",
      "Epoch   1 , loss = 0.3917\n",
      "Epoch   1 , loss = 0.7105\n",
      "Epoch   2 , loss = 0.6719\n",
      "Epoch   2 , loss = 0.3529\n",
      "Epoch   2 , loss = 0.2258\n",
      "Epoch   2 , loss = 0.2024\n",
      "Epoch   2 , loss = 0.1686\n",
      "Epoch   3 , loss = 0.3312\n",
      "Epoch   3 , loss = 0.2280\n",
      "Epoch   3 , loss = 0.1698\n",
      "Epoch   3 , loss = 0.1468\n",
      "Epoch   3 , loss = 0.0765\n",
      "Epoch   4 , loss = 0.1611\n",
      "Epoch   4 , loss = 0.1667\n",
      "Epoch   4 , loss = 0.1306\n",
      "Epoch   4 , loss = 0.1245\n",
      "Epoch   4 , loss = 0.0589\n",
      "Epoch   5 , loss = 0.1498\n",
      "Epoch   5 , loss = 0.1046\n",
      "Epoch   5 , loss = 0.1141\n",
      "Epoch   5 , loss = 0.1020\n",
      "Epoch   5 , loss = 0.0759\n",
      "Epoch   6 , loss = 0.0905\n",
      "Epoch   6 , loss = 0.1027\n",
      "Epoch   6 , loss = 0.0789\n",
      "Epoch   6 , loss = 0.0856\n",
      "Epoch   6 , loss = 0.0857\n",
      "Epoch   7 , loss = 0.1496\n",
      "Epoch   7 , loss = 0.0656\n",
      "Epoch   7 , loss = 0.0884\n",
      "Epoch   7 , loss = 0.0646\n",
      "Epoch   7 , loss = 0.0301\n",
      "Epoch   8 , loss = 0.0613\n",
      "Epoch   8 , loss = 0.0711\n",
      "Epoch   8 , loss = 0.0627\n",
      "Epoch   8 , loss = 0.0778\n",
      "Epoch   8 , loss = 0.0731\n",
      "Epoch   9 , loss = 0.0571\n",
      "Epoch   9 , loss = 0.0559\n",
      "Epoch   9 , loss = 0.0758\n",
      "Epoch   9 , loss = 0.0543\n",
      "Epoch   9 , loss = 0.0933\n",
      "Epoch  10 , loss = 0.1020\n",
      "Epoch  10 , loss = 0.0673\n",
      "Epoch  10 , loss = 0.0517\n",
      "Epoch  10 , loss = 0.0454\n",
      "Epoch  10 , loss = 0.0249\n",
      "Epoch  11 , loss = 0.0562\n",
      "Epoch  11 , loss = 0.0516\n",
      "Epoch  11 , loss = 0.0554\n",
      "Epoch  11 , loss = 0.0384\n",
      "Epoch  11 , loss = 0.0728\n",
      "Epoch  12 , loss = 0.0424\n",
      "Epoch  12 , loss = 0.0390\n",
      "Epoch  12 , loss = 0.0530\n",
      "Epoch  12 , loss = 0.0436\n",
      "Epoch  12 , loss = 0.0360\n",
      "Epoch  13 , loss = 0.0461\n",
      "Epoch  13 , loss = 0.0420\n",
      "Epoch  13 , loss = 0.0372\n",
      "Epoch  13 , loss = 0.0398\n",
      "Epoch  13 , loss = 0.0226\n",
      "Epoch  14 , loss = 0.0386\n",
      "Epoch  14 , loss = 0.0394\n",
      "Epoch  14 , loss = 0.0366\n",
      "Epoch  14 , loss = 0.0382\n",
      "Epoch  14 , loss = 0.0153\n",
      "Epoch  15 , loss = 0.0473\n",
      "Epoch  15 , loss = 0.0368\n",
      "Epoch  15 , loss = 0.0329\n",
      "Epoch  15 , loss = 0.0248\n",
      "Epoch  15 , loss = 0.1056\n",
      "Epoch  16 , loss = 0.0528\n",
      "Epoch  16 , loss = 0.0353\n",
      "Epoch  16 , loss = 0.0379\n",
      "Epoch  16 , loss = 0.0369\n",
      "Epoch  16 , loss = 0.0109\n",
      "Epoch  17 , loss = 0.0362\n",
      "Epoch  17 , loss = 0.0326\n",
      "Epoch  17 , loss = 0.0384\n",
      "Epoch  17 , loss = 0.0298\n",
      "Epoch  17 , loss = 0.0181\n",
      "Epoch  18 , loss = 0.0414\n",
      "Epoch  18 , loss = 0.0221\n",
      "Epoch  18 , loss = 0.0353\n",
      "Epoch  18 , loss = 0.0363\n",
      "Epoch  18 , loss = 0.0238\n",
      "Epoch  19 , loss = 0.0369\n",
      "Epoch  19 , loss = 0.0252\n",
      "Epoch  19 , loss = 0.0247\n",
      "Epoch  19 , loss = 0.0292\n",
      "Epoch  19 , loss = 0.0147\n",
      "Epoch  20 , loss = 0.0303\n",
      "Epoch  20 , loss = 0.0310\n",
      "Epoch  20 , loss = 0.0323\n",
      "Epoch  20 , loss = 0.0237\n",
      "Epoch  20 , loss = 0.0105\n",
      "Epoch  21 , loss = 0.0305\n",
      "Epoch  21 , loss = 0.0230\n",
      "Epoch  21 , loss = 0.0309\n",
      "Epoch  21 , loss = 0.0181\n",
      "Epoch  21 , loss = 0.1304\n",
      "Epoch  22 , loss = 0.0280\n",
      "Epoch  22 , loss = 0.0291\n",
      "Epoch  22 , loss = 0.0236\n",
      "Epoch  22 , loss = 0.0315\n",
      "Epoch  22 , loss = 0.0786\n",
      "Epoch  23 , loss = 0.0405\n",
      "Epoch  23 , loss = 0.0237\n",
      "Epoch  23 , loss = 0.0266\n",
      "Epoch  23 , loss = 0.0200\n",
      "Epoch  23 , loss = 0.0573\n",
      "Epoch  24 , loss = 0.0229\n",
      "Epoch  24 , loss = 0.0290\n",
      "Epoch  24 , loss = 0.0188\n",
      "Epoch  24 , loss = 0.0229\n",
      "Epoch  24 , loss = 0.0245\n",
      "Epoch  25 , loss = 0.0193\n",
      "Epoch  25 , loss = 0.0393\n",
      "Epoch  25 , loss = 0.0198\n",
      "Epoch  25 , loss = 0.0134\n",
      "Epoch  25 , loss = 0.0186\n",
      "Epoch  26 , loss = 0.0396\n",
      "Epoch  26 , loss = 0.0223\n",
      "Epoch  26 , loss = 0.0203\n",
      "Epoch  26 , loss = 0.0239\n",
      "Epoch  26 , loss = 0.0088\n",
      "Epoch  27 , loss = 0.0221\n",
      "Epoch  27 , loss = 0.0175\n",
      "Epoch  27 , loss = 0.0168\n",
      "Epoch  27 , loss = 0.0303\n",
      "Epoch  27 , loss = 0.0322\n",
      "Epoch  28 , loss = 0.0181\n",
      "Epoch  28 , loss = 0.0231\n",
      "Epoch  28 , loss = 0.0222\n",
      "Epoch  28 , loss = 0.0283\n",
      "Epoch  28 , loss = 0.0124\n",
      "Epoch  29 , loss = 0.0237\n",
      "Epoch  29 , loss = 0.0166\n",
      "Epoch  29 , loss = 0.0152\n",
      "Epoch  29 , loss = 0.0335\n",
      "Epoch  29 , loss = 0.0219\n",
      "Epoch  30 , loss = 0.0300\n",
      "Epoch  30 , loss = 0.0196\n",
      "Epoch  30 , loss = 0.0179\n",
      "Epoch  30 , loss = 0.0181\n",
      "Epoch  30 , loss = 0.0216\n",
      "Epoch  31 , loss = 0.0206\n",
      "Epoch  31 , loss = 0.0281\n",
      "Epoch  31 , loss = 0.0217\n",
      "Epoch  31 , loss = 0.0129\n",
      "Epoch  31 , loss = 0.0151\n",
      "Epoch  32 , loss = 0.0229\n",
      "Epoch  32 , loss = 0.0236\n",
      "Epoch  32 , loss = 0.0117\n",
      "Epoch  32 , loss = 0.0286\n",
      "Epoch  32 , loss = 0.0067\n",
      "Epoch  33 , loss = 0.0159\n",
      "Epoch  33 , loss = 0.0255\n",
      "Epoch  33 , loss = 0.0164\n",
      "Epoch  33 , loss = 0.0214\n",
      "Epoch  33 , loss = 0.0057\n",
      "Epoch  34 , loss = 0.0150\n",
      "Epoch  34 , loss = 0.0171\n",
      "Epoch  34 , loss = 0.0190\n",
      "Epoch  34 , loss = 0.0236\n",
      "Epoch  34 , loss = 0.0295\n",
      "Epoch  35 , loss = 0.0312\n",
      "Epoch  35 , loss = 0.0171\n",
      "Epoch  35 , loss = 0.0156\n",
      "Epoch  35 , loss = 0.0202\n",
      "Epoch  35 , loss = 0.0056\n",
      "Epoch  36 , loss = 0.0110\n",
      "Epoch  36 , loss = 0.0182\n",
      "Epoch  36 , loss = 0.0162\n",
      "Epoch  36 , loss = 0.0244\n",
      "Epoch  36 , loss = 0.0831\n",
      "Epoch  37 , loss = 0.0232\n",
      "Epoch  37 , loss = 0.0275\n",
      "Epoch  37 , loss = 0.0207\n",
      "Epoch  37 , loss = 0.0193\n",
      "Epoch  37 , loss = 0.0060\n",
      "Epoch  38 , loss = 0.0148\n",
      "Epoch  38 , loss = 0.0238\n",
      "Epoch  38 , loss = 0.0189\n",
      "Epoch  38 , loss = 0.0184\n",
      "Epoch  38 , loss = 0.0104\n",
      "Epoch  39 , loss = 0.0198\n",
      "Epoch  39 , loss = 0.0164\n",
      "Epoch  39 , loss = 0.0223\n",
      "Epoch  39 , loss = 0.0138\n",
      "Epoch  39 , loss = 0.0053\n",
      "Epoch  40 , loss = 0.0192\n",
      "Epoch  40 , loss = 0.0216\n",
      "Epoch  40 , loss = 0.0160\n",
      "Epoch  40 , loss = 0.0130\n",
      "Epoch  40 , loss = 0.0019\n",
      "Epoch  41 , loss = 0.0265\n",
      "Epoch  41 , loss = 0.0122\n",
      "Epoch  41 , loss = 0.0139\n",
      "Epoch  41 , loss = 0.0178\n",
      "Epoch  41 , loss = 0.0189\n",
      "Epoch  42 , loss = 0.0186\n",
      "Epoch  42 , loss = 0.0163\n",
      "Epoch  42 , loss = 0.0111\n",
      "Epoch  42 , loss = 0.0244\n",
      "Epoch  42 , loss = 0.0063\n",
      "Epoch  43 , loss = 0.0231\n",
      "Epoch  43 , loss = 0.0084\n",
      "Epoch  43 , loss = 0.0157\n",
      "Epoch  43 , loss = 0.0203\n",
      "Epoch  43 , loss = 0.0132\n",
      "Epoch  44 , loss = 0.0252\n",
      "Epoch  44 , loss = 0.0163\n",
      "Epoch  44 , loss = 0.0165\n",
      "Epoch  44 , loss = 0.0169\n",
      "Epoch  44 , loss = 0.0046\n",
      "Epoch  45 , loss = 0.0112\n",
      "Epoch  45 , loss = 0.0124\n",
      "Epoch  45 , loss = 0.0188\n",
      "Epoch  45 , loss = 0.0229\n",
      "Epoch  45 , loss = 0.0231\n",
      "Epoch  46 , loss = 0.0220\n",
      "Epoch  46 , loss = 0.0127\n",
      "Epoch  46 , loss = 0.0156\n",
      "Epoch  46 , loss = 0.0199\n",
      "Epoch  46 , loss = 0.0077\n",
      "Epoch  47 , loss = 0.0120\n",
      "Epoch  47 , loss = 0.0112\n",
      "Epoch  47 , loss = 0.0215\n",
      "Epoch  47 , loss = 0.0205\n",
      "Epoch  47 , loss = 0.0090\n",
      "Epoch  48 , loss = 0.0282\n",
      "Epoch  48 , loss = 0.0177\n",
      "Epoch  48 , loss = 0.0123\n",
      "Epoch  48 , loss = 0.0098\n",
      "Epoch  48 , loss = 0.0183\n",
      "Epoch  49 , loss = 0.0196\n",
      "Epoch  49 , loss = 0.0116\n",
      "Epoch  49 , loss = 0.0142\n",
      "Epoch  49 , loss = 0.0191\n",
      "Epoch  49 , loss = 0.0061\n",
      "Epoch  50 , loss = 0.0141\n",
      "Epoch  50 , loss = 0.0166\n",
      "Epoch  50 , loss = 0.0216\n",
      "Epoch  50 , loss = 0.0129\n",
      "Epoch  50 , loss = 0.0159\n",
      "Epoch  51 , loss = 0.0136\n",
      "Epoch  51 , loss = 0.0172\n",
      "Epoch  51 , loss = 0.0157\n",
      "Epoch  51 , loss = 0.0194\n",
      "Epoch  51 , loss = 0.0032\n",
      "Epoch  52 , loss = 0.0169\n",
      "Epoch  52 , loss = 0.0110\n",
      "Epoch  52 , loss = 0.0257\n",
      "Epoch  52 , loss = 0.0086\n",
      "Epoch  52 , loss = 0.0297\n",
      "Epoch  53 , loss = 0.0142\n",
      "Epoch  53 , loss = 0.0142\n",
      "Epoch  53 , loss = 0.0214\n",
      "Epoch  53 , loss = 0.0143\n",
      "Epoch  53 , loss = 0.0070\n",
      "Epoch  54 , loss = 0.0182\n",
      "Epoch  54 , loss = 0.0131\n",
      "Epoch  54 , loss = 0.0168\n",
      "Epoch  54 , loss = 0.0161\n",
      "Epoch  54 , loss = 0.0193\n",
      "Epoch  55 , loss = 0.0154\n",
      "Epoch  55 , loss = 0.0189\n",
      "Epoch  55 , loss = 0.0148\n",
      "Epoch  55 , loss = 0.0144\n",
      "Epoch  55 , loss = 0.0060\n",
      "Epoch  56 , loss = 0.0171\n",
      "Epoch  56 , loss = 0.0115\n",
      "Epoch  56 , loss = 0.0143\n",
      "Epoch  56 , loss = 0.0204\n",
      "Epoch  56 , loss = 0.0030\n",
      "Epoch  57 , loss = 0.0133\n",
      "Epoch  57 , loss = 0.0129\n",
      "Epoch  57 , loss = 0.0124\n",
      "Epoch  57 , loss = 0.0224\n",
      "Epoch  57 , loss = 0.0326\n",
      "Epoch  58 , loss = 0.0228\n",
      "Epoch  58 , loss = 0.0093\n",
      "Epoch  58 , loss = 0.0153\n",
      "Epoch  58 , loss = 0.0141\n",
      "Epoch  58 , loss = 0.0094\n",
      "Epoch  59 , loss = 0.0175\n",
      "Epoch  59 , loss = 0.0163\n",
      "Epoch  59 , loss = 0.0185\n",
      "Epoch  59 , loss = 0.0099\n",
      "Epoch  59 , loss = 0.0021\n",
      "Epoch  60 , loss = 0.0233\n",
      "Epoch  60 , loss = 0.0132\n",
      "Epoch  60 , loss = 0.0119\n",
      "Epoch  60 , loss = 0.0124\n",
      "Epoch  60 , loss = 0.0055\n",
      "Epoch  61 , loss = 0.0104\n",
      "Epoch  61 , loss = 0.0138\n",
      "Epoch  61 , loss = 0.0119\n",
      "Epoch  61 , loss = 0.0263\n",
      "Epoch  61 , loss = 0.0074\n",
      "Epoch  62 , loss = 0.0181\n",
      "Epoch  62 , loss = 0.0081\n",
      "Epoch  62 , loss = 0.0267\n",
      "Epoch  62 , loss = 0.0106\n",
      "Epoch  62 , loss = 0.0027\n",
      "Epoch  63 , loss = 0.0223\n",
      "Epoch  63 , loss = 0.0111\n",
      "Epoch  63 , loss = 0.0098\n",
      "Epoch  63 , loss = 0.0158\n",
      "Epoch  63 , loss = 0.0206\n",
      "Epoch  64 , loss = 0.0182\n",
      "Epoch  64 , loss = 0.0111\n",
      "Epoch  64 , loss = 0.0127\n",
      "Epoch  64 , loss = 0.0190\n",
      "Epoch  64 , loss = 0.0013\n",
      "Epoch  65 , loss = 0.0142\n",
      "Epoch  65 , loss = 0.0124\n",
      "Epoch  65 , loss = 0.0174\n",
      "Epoch  65 , loss = 0.0149\n",
      "Epoch  65 , loss = 0.0068\n",
      "Epoch  66 , loss = 0.0100\n",
      "Epoch  66 , loss = 0.0213\n",
      "Epoch  66 , loss = 0.0109\n",
      "Epoch  66 , loss = 0.0164\n",
      "Epoch  66 , loss = 0.0036\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch  67 , loss = 0.0139\n",
      "Epoch  67 , loss = 0.0173\n",
      "Epoch  67 , loss = 0.0155\n",
      "Epoch  67 , loss = 0.0081\n",
      "Epoch  67 , loss = 0.0942\n",
      "Epoch  68 , loss = 0.0212\n",
      "Epoch  68 , loss = 0.0175\n",
      "Epoch  68 , loss = 0.0185\n",
      "Epoch  68 , loss = 0.0155\n",
      "Epoch  68 , loss = 0.0218\n",
      "Epoch  69 , loss = 0.0248\n",
      "Epoch  69 , loss = 0.0191\n",
      "Epoch  69 , loss = 0.0130\n",
      "Epoch  69 , loss = 0.0098\n",
      "Epoch  69 , loss = 0.0068\n",
      "Epoch  70 , loss = 0.0180\n",
      "Epoch  70 , loss = 0.0120\n",
      "Epoch  70 , loss = 0.0146\n",
      "Epoch  70 , loss = 0.0161\n",
      "Epoch  70 , loss = 0.0005\n",
      "Epoch  71 , loss = 0.0118\n",
      "Epoch  71 , loss = 0.0152\n",
      "Epoch  71 , loss = 0.0079\n",
      "Epoch  71 , loss = 0.0225\n",
      "Epoch  71 , loss = 0.0305\n",
      "Epoch  72 , loss = 0.0214\n",
      "Epoch  72 , loss = 0.0212\n",
      "Epoch  72 , loss = 0.0105\n",
      "Epoch  72 , loss = 0.0110\n",
      "Epoch  72 , loss = 0.0105\n",
      "Epoch  73 , loss = 0.0129\n",
      "Epoch  73 , loss = 0.0152\n",
      "Epoch  73 , loss = 0.0153\n",
      "Epoch  73 , loss = 0.0135\n",
      "Epoch  73 , loss = 0.0044\n",
      "Epoch  74 , loss = 0.0139\n",
      "Epoch  74 , loss = 0.0109\n",
      "Epoch  74 , loss = 0.0174\n",
      "Epoch  74 , loss = 0.0148\n",
      "Epoch  74 , loss = 0.0019\n",
      "Epoch  75 , loss = 0.0137\n",
      "Epoch  75 , loss = 0.0119\n",
      "Epoch  75 , loss = 0.0111\n",
      "Epoch  75 , loss = 0.0178\n",
      "Epoch  75 , loss = 0.0453\n",
      "Epoch  76 , loss = 0.0453\n",
      "Epoch  76 , loss = 0.0109\n",
      "Epoch  76 , loss = 0.0173\n",
      "Epoch  76 , loss = 0.0109\n",
      "Epoch  76 , loss = 0.0026\n",
      "Epoch  77 , loss = 0.0260\n",
      "Epoch  77 , loss = 0.0065\n",
      "Epoch  77 , loss = 0.0161\n",
      "Epoch  77 , loss = 0.0122\n",
      "Epoch  77 , loss = 0.0021\n",
      "Epoch  78 , loss = 0.0112\n",
      "Epoch  78 , loss = 0.0191\n",
      "Epoch  78 , loss = 0.0093\n",
      "Epoch  78 , loss = 0.0172\n",
      "Epoch  78 , loss = 0.0010\n",
      "Epoch  79 , loss = 0.0157\n",
      "Epoch  79 , loss = 0.0125\n",
      "Epoch  79 , loss = 0.0125\n",
      "Epoch  79 , loss = 0.0150\n",
      "Epoch  79 , loss = 0.0035\n",
      "Epoch  80 , loss = 0.0146\n",
      "Epoch  80 , loss = 0.0171\n",
      "Epoch  80 , loss = 0.0108\n",
      "Epoch  80 , loss = 0.0133\n",
      "Epoch  80 , loss = 0.0037\n",
      "Epoch  81 , loss = 0.0099\n",
      "Epoch  81 , loss = 0.0111\n",
      "Epoch  81 , loss = 0.0085\n",
      "Epoch  81 , loss = 0.0273\n",
      "Epoch  81 , loss = 0.0098\n",
      "Epoch  82 , loss = 0.0104\n",
      "Epoch  82 , loss = 0.0166\n",
      "Epoch  82 , loss = 0.0110\n",
      "Epoch  82 , loss = 0.0168\n",
      "Epoch  82 , loss = 0.0170\n",
      "Epoch  83 , loss = 0.0109\n",
      "Epoch  83 , loss = 0.0184\n",
      "Epoch  83 , loss = 0.0171\n",
      "Epoch  83 , loss = 0.0134\n",
      "Epoch  83 , loss = 0.0012\n",
      "Epoch  84 , loss = 0.0087\n",
      "Epoch  84 , loss = 0.0136\n",
      "Epoch  84 , loss = 0.0188\n",
      "Epoch  84 , loss = 0.0142\n",
      "Epoch  84 , loss = 0.0069\n",
      "Epoch  85 , loss = 0.0106\n",
      "Epoch  85 , loss = 0.0164\n",
      "Epoch  85 , loss = 0.0150\n",
      "Epoch  85 , loss = 0.0120\n",
      "Epoch  85 , loss = 0.0107\n",
      "Epoch  86 , loss = 0.0115\n",
      "Epoch  86 , loss = 0.0125\n",
      "Epoch  86 , loss = 0.0136\n",
      "Epoch  86 , loss = 0.0167\n",
      "Epoch  86 , loss = 0.0496\n",
      "Epoch  87 , loss = 0.0238\n",
      "Epoch  87 , loss = 0.0215\n",
      "Epoch  87 , loss = 0.0101\n",
      "Epoch  87 , loss = 0.0124\n",
      "Epoch  87 , loss = 0.0055\n",
      "Epoch  88 , loss = 0.0120\n",
      "Epoch  88 , loss = 0.0150\n",
      "Epoch  88 , loss = 0.0111\n",
      "Epoch  88 , loss = 0.0175\n",
      "Epoch  88 , loss = 0.0045\n",
      "Epoch  89 , loss = 0.0092\n",
      "Epoch  89 , loss = 0.0129\n",
      "Epoch  89 , loss = 0.0125\n",
      "Epoch  89 , loss = 0.0198\n",
      "Epoch  89 , loss = 0.0076\n",
      "Epoch  90 , loss = 0.0114\n",
      "Epoch  90 , loss = 0.0128\n",
      "Epoch  90 , loss = 0.0167\n",
      "Epoch  90 , loss = 0.0155\n",
      "Epoch  90 , loss = 0.0115\n",
      "Epoch  91 , loss = 0.0130\n",
      "Epoch  91 , loss = 0.0174\n",
      "Epoch  91 , loss = 0.0128\n",
      "Epoch  91 , loss = 0.0140\n",
      "Epoch  91 , loss = 0.0189\n",
      "Epoch  92 , loss = 0.0104\n",
      "Epoch  92 , loss = 0.0107\n",
      "Epoch  92 , loss = 0.0214\n",
      "Epoch  92 , loss = 0.0112\n",
      "Epoch  92 , loss = 0.0019\n",
      "Epoch  93 , loss = 0.0192\n",
      "Epoch  93 , loss = 0.0158\n",
      "Epoch  93 , loss = 0.0091\n",
      "Epoch  93 , loss = 0.0097\n",
      "Epoch  93 , loss = 0.0023\n",
      "Epoch  94 , loss = 0.0129\n",
      "Epoch  94 , loss = 0.0177\n",
      "Epoch  94 , loss = 0.0091\n",
      "Epoch  94 , loss = 0.0138\n",
      "Epoch  94 , loss = 0.0018\n",
      "Epoch  95 , loss = 0.0149\n",
      "Epoch  95 , loss = 0.0107\n",
      "Epoch  95 , loss = 0.0146\n",
      "Epoch  95 , loss = 0.0125\n",
      "Epoch  95 , loss = 0.0060\n",
      "Epoch  96 , loss = 0.0107\n",
      "Epoch  96 , loss = 0.0123\n",
      "Epoch  96 , loss = 0.0110\n",
      "Epoch  96 , loss = 0.0177\n",
      "Epoch  96 , loss = 0.0436\n",
      "Epoch  97 , loss = 0.0302\n",
      "Epoch  97 , loss = 0.0140\n",
      "Epoch  97 , loss = 0.0115\n",
      "Epoch  97 , loss = 0.0146\n",
      "Epoch  97 , loss = 0.0120\n",
      "Epoch  98 , loss = 0.0120\n",
      "Epoch  98 , loss = 0.0114\n",
      "Epoch  98 , loss = 0.0137\n",
      "Epoch  98 , loss = 0.0172\n",
      "Epoch  98 , loss = 0.0023\n",
      "Epoch  99 , loss = 0.0116\n",
      "Epoch  99 , loss = 0.0181\n",
      "Epoch  99 , loss = 0.0114\n",
      "Epoch  99 , loss = 0.0124\n",
      "Epoch  99 , loss = 0.0124\n"
     ]
    },
    {
     "data": {
      "image/png": "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Tl13ndDQUF122WUaN26c5s+fr1GjRumZZ56hjrvQtm3bVFRUpLFjxyo4OFjBwcFat26dFi1apODgYLOuqOuuFxkZqSuuuELZ2dkX3c+0LcNIaGioxo4dq8zMTL/jmZmZmjRpkkWl+mJJT09XYmKiXx273W6tW7fOrOOxY8cqJCTE75yCggLt2bOHfwcfhmHowQcf1LJly7R69Wqlp6f7PU9dB45hGKqtraWOu9D06dO1e/du7dy507yNGzdO3/nOd7Rz504NHDiQug6Q2tpa7d+/X0lJSRffz3SXDoe9hHin9r7yyivGvn37jEceecSIjIw0jh07ZnXRLhnl5eXGjh07jB07dhiSjKefftrYsWOHOT36qaeeMmJjY41ly5YZu3fvNr797W+3Om0sJSXF+Oijj4zt27cbX/rSl5ied5Yf/vCHRmxsrLF27Vq/KXpVVVXmOdR1582dO9dYv369cfToUWPXrl3GvHnzDKfTaaxatcowDOo4kHxn0xgGdd1VfvKTnxhr1641jhw5YmzevNm4+eabjejoaPNz7mKqZ9uGEcMwjOeee87o37+/ERoaaowZM8acKon2WbNmjSGpxe3uu+82DKNx6tiTTz5pJCYmGmFhYcbUqVON3bt3+71GdXW18eCDDxq9evUyIiIijJtvvtnIycmx4Lu5eLVWx5KM1157zTyHuu68++67z/x90LdvX2P69OlmEDEM6jiQzg4j1HXX8K4bEhISYiQnJxtf//rXjb1795rPX0z17DAMw+jathYAAID2s+WYEQAAcPEgjAAAAEsRRgAAgKUIIwAAwFKEEQAAYCnCCAAAsBRhBAAAWIowAgAALEUYAQAAliKMAAAASxFGAACApQgjAADAUv8fzqqdwN9IQ3oAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练完毕，请输入要预测的数据\n",
      "0.00632 18.0 2.31 0.0 0.538 6.575 65.2 4.0900 1 296 15.3 396.90 4.98\n",
      "预测结果为\n",
      "[31.94718754672006]\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "import matplotlib.pyplot as plt\n",
    "import pickle\n",
    "#读取数据集\n",
    "def read_data(filename):\n",
    "    # 读取数据集\n",
    "    datafile = open(filename)\n",
    "    feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE',\n",
    "                     'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']\n",
    "    feature_num = len(feature_names)\n",
    "\n",
    "    data = []\n",
    "    for line in datafile:\n",
    "        data.append(list(map(float, line.split())))\n",
    "\n",
    "    # 均一化\n",
    "    cols = [[one[i] for one in data] for i in range(feature_num)]\n",
    "    maximums = []\n",
    "    minimums = []\n",
    "    avg = []\n",
    "\n",
    "    for i in range(feature_num):\n",
    "        maximums.append(max(cols[i]))\n",
    "        minimums.append(min(cols[i]))\n",
    "        avg.append(sum(cols[i]) / len(cols[i]))\n",
    "\n",
    "    for one in data:\n",
    "        for i in range(feature_num):\n",
    "            # print(maximums[i], minimums[i], avgs[i])\n",
    "            one[i] = (one[i] - avg[i]) / (maximums[i] - minimums[i])\n",
    "\n",
    "    # 分割数据集，分为训练集和测试集\n",
    "    ratio = 0.8\n",
    "    training_data = data[:int(0.8 * len(data))]\n",
    "    test_data = data[int(0.8 * len(data)):]\n",
    "\n",
    "    return training_data, feature_num, avg, maximums, minimums\n",
    "\n",
    "class Network(object):\n",
    "\n",
    "    def __init__(self, num_of_weights):\n",
    "        self.W_1 = []\n",
    "        self.W_2 = []\n",
    "        self.B_1 = []\n",
    "        self.B_2 = (random.uniform(0, 2.0)-1)\n",
    "        for i in range(feature_num - 1):\n",
    "            w = []\n",
    "            for j in range(feature_num - 1):\n",
    "                w.append((random.uniform(0, 2.0)-1))\n",
    "            self.W_1.append(w)\n",
    "            self.W_2.append((random.uniform(0, 2.0)-1))\n",
    "            self.B_1.append((random.uniform(0, 2.0)-1))\n",
    "        self.eta = 0.1\n",
    "\n",
    "    def load(self):\n",
    "        with open('save.data', 'rb') as savefile:\n",
    "            save=pickle.load(savefile)\n",
    "            self.W_1=save[0]\n",
    "            self.W_2=save[1]\n",
    "            self.B_1=save[2]\n",
    "            self.B_2=save[3]\n",
    "\n",
    "    def forward(self, data_pack):\n",
    "        Z_1_result = []\n",
    "        Z_2_result = []\n",
    "        for one in data_pack:\n",
    "            z = 0\n",
    "            Z_1 = []\n",
    "            Z_2 = 0\n",
    "            for i in range(feature_num - 1):\n",
    "                for j in range(feature_num - 1):\n",
    "                    z += self.W_1[i][j] * one[j]\n",
    "                z += self.B_1[i]\n",
    "                Z_1.append(z)\n",
    "                z = 0\n",
    "            Z_1_result.append(Z_1)\n",
    "            for i in range(feature_num - 1):\n",
    "                Z_2 += Z_1[i]*self.W_2[i]\n",
    "            Z_2 += self.B_2\n",
    "            Z_2_result.append(Z_2)\n",
    "        return Z_1_result, Z_2_result\n",
    "\n",
    "    def loss(self, z, real): # 计算损失函数\n",
    "        cost = []\n",
    "        for i in range(len(z)):\n",
    "            error = z[i] - real[i]\n",
    "            costone = error**2\n",
    "            cost.append(costone)\n",
    "            pass\n",
    "\n",
    "        res = sum(cost) / len(z)\n",
    "        return res\n",
    "\n",
    "    def gradient(self, x, real, z1, z2): # 计算梯度\n",
    "        gradient_W_1 = []\n",
    "        gradient_W_2 = []\n",
    "        gradient_B_1 = []\n",
    "        gradient_B_2 = []\n",
    "\n",
    "        for n in range(len(x)):\n",
    "\n",
    "            tmp_g = (z2[n]-real[n])\n",
    "            gradient_B_2.append(tmp_g)\n",
    "\n",
    "            gradient_w2 = []\n",
    "            for i in range(feature_num - 1):\n",
    "                gradient_w2.append(tmp_g * z1[n][i])\n",
    "            gradient_W_2.append(gradient_w2)\n",
    "\n",
    "            gradient_b1 = []\n",
    "            for i in range(feature_num - 1):\n",
    "                gradient_b1.append(tmp_g * self.W_2[i])\n",
    "            gradient_B_1.append(gradient_b1)\n",
    "\n",
    "            gradient_w1 = []\n",
    "            for i in range(feature_num - 1):\n",
    "                g_line_w1 = []\n",
    "                for j in range(feature_num - 1):\n",
    "                    g_line_w1.append(tmp_g * self.W_2[i] * x[n][j])\n",
    "                gradient_w1.append(g_line_w1)\n",
    "            gradient_W_1.append(gradient_w1)\n",
    "        #求和取平均\n",
    "        cols_W_2 = [[one[i] for one in gradient_W_2] for i in range(feature_num - 1)]\n",
    "        cols_B_1 = [[one[i] for one in gradient_B_1] for i in range(feature_num - 1)]\n",
    "        cols_W_1 = [[[one[i][j] for one in gradient_W_1]for j in range(feature_num - 1)] for i in range(feature_num -1)]\n",
    "        aver_W_2 = []\n",
    "        aver_B_1 = []\n",
    "        aver_W_1 = []\n",
    "        for i in range(feature_num - 1):\n",
    "            aver_W_2.append(sum(cols_W_2[i]) / len(cols_W_2[i]))\n",
    "            aver_B_1.append(sum(cols_B_1[i]) / len(cols_B_1[i]))\n",
    "            aver_w1 = []\n",
    "            for j in range(feature_num - 1):\n",
    "                aver_w1.append(sum(cols_W_1[i][j]) / len(cols_W_1[i][j]))\n",
    "            aver_W_1.append(aver_w1)\n",
    "        aver_B_2 = sum(gradient_B_2) / len(gradient_B_2)\n",
    "\n",
    "        return aver_W_1, aver_W_2, aver_B_1, aver_B_2\n",
    "\n",
    "    def update(self, gradient_w1, gradient_w2, gradient_b1, gradient_b2, eta=0.1):\n",
    "        self.B_2 = self.B_2 - eta * gradient_b2\n",
    "        for i in range(feature_num - 1):\n",
    "            self.B_1[i] = self.B_1[i] - eta * gradient_b1[i]\n",
    "            self.W_2[i] = self.W_2[i] - eta * gradient_w2[i]\n",
    "            for j in range(feature_num - 1):\n",
    "                self.W_1[i][j] = self.W_1[i][j] - eta * gradient_w1[i][j]\n",
    "\n",
    "    def train(self, training_data, num_epoches=100, batch_size=100):\n",
    "        num = len(training_data)\n",
    "        losses = []\n",
    "        for epoch_id in range(num_epoches):\n",
    "            # 在每轮迭代开始之前，将训练数据的顺序随机的打乱，\n",
    "            random.shuffle(training_data)\n",
    "            x_all = [i[:-1] for i in training_data]\n",
    "            y_all = [i[-1:][0] for i in training_data]\n",
    "\n",
    "            for i in range(0, num, batch_size):\n",
    "                x = x_all[i:i + batch_size]\n",
    "                y = y_all[i:i + batch_size]\n",
    "                z1, z2 = self.forward(x)\n",
    "                loss = self.loss(z2, y)\n",
    "                gradient_w1, gradient_w2, gradient_b1, gradient_b2 = self.gradient(x, y, z1, z2)\n",
    "                self.update(gradient_w1, gradient_w2, gradient_b1, gradient_b2, self.eta)\n",
    "                losses.append(loss)\n",
    "                print('Epoch {:3d} , loss = {:.4f}'.\n",
    "                      format(epoch_id, loss))\n",
    "        save = []\n",
    "        save.append(self.W_1)\n",
    "        save.append(self.W_2)\n",
    "        save.append(self.B_1)\n",
    "        save.append(self.B_2)\n",
    "        with open('save.data', 'wb') as savefile:\n",
    "            pickle.dump(save, savefile)\n",
    "\n",
    "        return losses\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    # 读取数据集\n",
    "    training_data, feature_num, avg, maximums, minimums = read_data('./housing.data')\n",
    "    # 启动训练\n",
    "    net = Network(13)\n",
    "    key=input(\"请选择\\n1 直接训练\\n2 使用已有的模型\\n\")\n",
    "    if key == '2' :\n",
    "        net.load()\n",
    "    else:\n",
    "        losses = net.train(training_data, num_epoches=100)\n",
    "        plot_x = range(len(losses))\n",
    "        plot_y = losses\n",
    "        plt.plot(plot_x, plot_y)\n",
    "        plt.show()\n",
    "    new = input(\"训练完毕，请输入要预测的数据\\n\")\n",
    "    new_pack = []\n",
    "    new_pack.append(list(map(float, new.split())))\n",
    "    for i in range(feature_num - 1):\n",
    "        # print(maximums[i], minimums[i], avg[i])\n",
    "        new_pack[0][i] = (new_pack[0][i] - avg[i]) / (maximums[i] - minimums[i])\n",
    "    newz1, newz2 = net.forward(new_pack)\n",
    "    # 将归一化的数据复原\n",
    "    newz2[0] = newz2[0]*(maximums[feature_num-1] - minimums[feature_num-1])+avg[feature_num-1]\n",
    "    print(\"预测结果为\")\n",
    "    print(newz2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ac19376",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
